/**********************************************
** @Des: This file ...
** @Author: xiaomeng79
** @Date:   17-11-20 下午6:07
***********************************************/
package models

import (
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/validation"
	"strings"
	"errors"
	"time"
	"github.com/xiaomeng79/go-rbac/libs"
	"strconv"
)

type Admin struct {
	Id int
	Username string
	Password string
	Salt string
	Sex uint8
	Created_at int64
	Updated_at int64
	Is_usable int
}

/**
设置表名称
 */
func (a *Admin) TableName() string {
	return "rbac_admin"
}

/**
增加
 */
func (a *Admin) Add(role_ids []int) (error) {
	if err := a.valid("add");err != nil {
		return err
	}
	o := orm.NewOrm()
	o.Begin()
	id,err := o.Insert(a)
	if err != nil {
		o.Rollback()
		return errors.New("新增管理员失败")
	}

	p,_ := o.Raw("INSERT INTO rbac_admin_role (admin_id,role_id) VALUES (?,?)").Prepare()
	for _,role_id := range role_ids {
		_,err = p.Exec(id,role_id)
		if err  != nil {
			o.Rollback()
			return errors.New("新增管理员角色失败")
		}
	}
	p.Close()
	o.Commit()
	return nil
}

/**
列表
 */
func (a *Admin) Lst() (interface{}) {
	o := orm.NewOrm()
	maps := make([]orm.Params,0)
	sql := `SELECT a.id,a.username,a.sex,a.created_at,GROUP_CONCAT(r.role_name) as role_names FROM rbac_admin AS a
			LEFT JOIN rbac_admin_role AS ar ON ar.admin_id = a.id
			LEFT JOIN rbac_role AS r ON r.id = ar.role_id AND r.is_usable = 1
			WHERE a.is_usable = 1
			GROUP BY a.id`
	o.Raw(sql).Values(&maps)
	return maps
}


/**
获取对象用ID
 */
func GetAdminById(id int) (map[string]interface{}, error) {
	o := orm.NewOrm()
	res := make([]orm.Params,1)
	sql := `SELECT a.id,a.username,a.sex,a.created_at,GROUP_CONCAT(ar.role_id) AS role_ids FROM rbac_admin AS a
			LEFT JOIN rbac_admin_role AS ar ON ar.admin_id = a.id
			WHERE a.is_usable = 1 AND a.id = ?
			GROUP BY a.id
			LIMIT 1`
	num, err := o.Raw(sql,id).Values(&res)
	if err != nil || num != 1 {
		return nil, errors.New("获取对象失败")
	}
	return res[0], nil
}

/**
判断用户是否有权限
 */
func (a *Admin) Is_Auth(id int,controller,action string) bool {
	o := orm.NewOrm()
	maps := make([]orm.Params,1)
	sql := `SELECT COUNT(*) AS num FROM rbac_admin_role AS ar
			LEFT JOIN rbac_role_pri AS rp ON rp.role_id = ar.role_id
			LEFT JOIN rbac_privilege AS p ON p.id = rp.pri_id
			WHERE ar.admin_id = ? AND p.controller_name = ? AND p.action_name = ? AND p.is_usable = 1`

	o.Raw(sql,id,controller,action).Values(&maps)
	num,_ := strconv.Atoi(libs.InterfaceToString(maps[0]["num"]))
	if num > 0 {
		return true;
	}
	return false;

}

/**
修改
 */
func (a *Admin) Edit(role_ids []int, fields ...string) (error) {

	o := orm.NewOrm()
	o.Begin()
	_,err := o.Update(a, fields...)

	if err != nil {
		o.Rollback()
		return errors.New("修改管理员失败")
	}
	p0, _ := o.Raw("DELETE FROM rbac_admin_role WHERE admin_id = ?").Prepare()
	if _,err =p0.Exec(a.Id);err != nil {
		o.Rollback()
		return errors.New("修改管理员失败")
	}

	p1,_ := o.Raw("INSERT INTO rbac_admin_role(admin_id,role_id) VALUES(?,?)").Prepare()
	for _,v := range role_ids {
		if _,err =p1.Exec(a.Id, v);err != nil {
			o.Rollback()
			return errors.New("修改管理员失败")
		}
	}
	p0.Close()
	p1.Close()
	o.Commit()
	return nil
}

/**
删除
 */
func (a *Admin) Del(id int) error {
	o := orm.NewOrm()
	p,_ := o.Raw("UPDATE  rbac_admin SET is_usable = 0,updated_at = ? where id = ?").Prepare()
	_,err := p.Exec(time.Now().Unix(),id)
	p.Close()
	if err != nil {
		return errors.New("删除管理员失败")
	}
	return nil
}

func (a *Admin) Login(username,password string) (map[string]interface{},error) {
	o := orm.NewOrm()
	res := make([]orm.Params,1)
	sql := "SELECT id,username,password,salt FROM rbac_admin WHERE is_usable = 1 AND username = ?"

	num, err := o.Raw(sql,username).Values(&res)
	if err != nil || num != 1 {
		return  nil,errors.New("用户不存在")
	}

	return res[0], nil

}


/**
数据验证
 */
func (a *Admin) valid(str string) (error) {
	v := validation.Validation{}

	//公共的
	if res := v.Required(a.Username, "用户名称"); !res.Ok {
		return errors.New(res.Error.Key+res.Error.Message)
	}

	if strings.Index(a.Username, "root") != -1 {
		// 通过 SetError 设置 Name 的错误信息，HasErrors 将会返回 true
		return errors.New("名称里不能含有 root")
	}
	//add需要验证的
	if str == "add" {
		if res := v.Required(a.Sex, "性别"); !res.Ok {
			return errors.New(res.Error.Key+res.Error.Message)
		}
		cnt,_ := orm.NewOrm().QueryTable(a.TableName()).Filter("username",a.Username).Filter("is_usable",1).Count()
		if cnt > 0 {
			return errors.New(a.Username+"用户已经存在")
		}
	}

	return nil

}

